package com.wenchao.quickstart.utils;

import android.content.Context;

import androidx.datastore.preferences.core.MutablePreferences;
import androidx.datastore.preferences.core.Preferences;
import androidx.datastore.preferences.core.PreferencesKeys;
import androidx.datastore.preferences.rxjava3.RxPreferenceDataStoreBuilder;
import androidx.datastore.rxjava3.RxDataStore;

import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.core.Single;

/**
 * 【类的描述】Preferences Datastore 替代 SP
 *
 * @author zhangwenchao
 * @date 2021-12-20
 */
public class PreferenceUtil {

    private static final String NAME = "super";

    private volatile static PreferenceUtil instance;
    private static RxDataStore<Preferences> dataStore;

    private PreferenceUtil() {
    }

    /**
     * 单一实例
     */
    public static PreferenceUtil getInstance() {
        if (instance == null) {
            synchronized (PreferenceUtil.class) {
                if (instance == null) {
                    instance = new PreferenceUtil();
                }
            }
        }
        return instance;
    }

    public void init(Context context) {
        dataStore = new RxPreferenceDataStoreBuilder(context, NAME).build();
    }

    public void initWithName(Context context, String name) {
        dataStore = new RxPreferenceDataStoreBuilder(context, name).build();
    }

    public void putString(String key, String value) {
        Preferences.Key<String> nameKey = PreferencesKeys.stringKey(key);
        Single<Preferences> updateResult = dataStore.updateDataAsync(prefsIn -> {
            MutablePreferences mutablePreferences = prefsIn.toMutablePreferences();
            mutablePreferences.set(nameKey, value);
            return Single.just(mutablePreferences);
        });
    }

    public void putInteger(String key, Integer value) {
        Preferences.Key<Integer> nameKey = PreferencesKeys.intKey(key);
        Single<Preferences> updateResult = dataStore.updateDataAsync(prefsIn -> {
            MutablePreferences mutablePreferences = prefsIn.toMutablePreferences();
            mutablePreferences.set(nameKey, value);
            return Single.just(mutablePreferences);
        });
    }

    public void putLong(String key, Long value) {
        Preferences.Key<Long> nameKey = PreferencesKeys.longKey(key);
        Single<Preferences> updateResult = dataStore.updateDataAsync(prefsIn -> {
            MutablePreferences mutablePreferences = prefsIn.toMutablePreferences();
            mutablePreferences.set(nameKey, value);
            return Single.just(mutablePreferences);
        });
    }

    public void putBoolean(String key, Boolean value) {
        Preferences.Key<Boolean> nameKey = PreferencesKeys.booleanKey(key);
        Single<Preferences> updateResult = dataStore.updateDataAsync(prefsIn -> {
            MutablePreferences mutablePreferences = prefsIn.toMutablePreferences();
            mutablePreferences.set(nameKey, value);
            return Single.just(mutablePreferences);
        });
    }

    public void putDouble(String key, Double value) {
        Preferences.Key<Double> nameKey = PreferencesKeys.doubleKey(key);
        Single<Preferences> updateResult = dataStore.updateDataAsync(prefsIn -> {
            MutablePreferences mutablePreferences = prefsIn.toMutablePreferences();
            mutablePreferences.set(nameKey, value);
            return Single.just(mutablePreferences);
        });
    }

    public void putFloat(String key, Float value) {
        Preferences.Key<Float> nameKey = PreferencesKeys.floatKey(key);
        Single<Preferences> updateResult = dataStore.updateDataAsync(prefsIn -> {
            MutablePreferences mutablePreferences = prefsIn.toMutablePreferences();
            mutablePreferences.set(nameKey, value);
            return Single.just(mutablePreferences);
        });
    }

    public String getString(String key) {
        try {
            Preferences.Key<String> nameKey = PreferencesKeys.stringKey(key);
            Flowable<String> exampleCounterFlow = dataStore.data().map(prefs -> prefs.get(nameKey));
            return exampleCounterFlow.blockingFirst();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public Integer getInteger(String key) {
        try {
            Preferences.Key<Integer> nameKey = PreferencesKeys.intKey(key);
            Flowable<Integer> exampleCounterFlow = dataStore.data().map(prefs -> prefs.get(nameKey));
            return exampleCounterFlow.blockingFirst();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public Long getLong(String key) {
        try {
            Preferences.Key<Long> nameKey = PreferencesKeys.longKey(key);
            Flowable<Long> exampleCounterFlow = dataStore.data().map(prefs -> prefs.get(nameKey));
            return exampleCounterFlow.blockingFirst();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public Boolean getBoolean(String key) {
        try {
            Preferences.Key<Boolean> nameKey = PreferencesKeys.booleanKey(key);
            Flowable<Boolean> exampleCounterFlow = dataStore.data().map(prefs -> prefs.get(nameKey));
            return exampleCounterFlow.blockingFirst();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public Double getDouble(String key) {
        try {
            Preferences.Key<Double> nameKey = PreferencesKeys.doubleKey(key);
            Flowable<Double> exampleCounterFlow = dataStore.data().map(prefs -> prefs.get(nameKey));
            return exampleCounterFlow.blockingFirst();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0.0;
    }

    public Float getFloat(String key) {
        try {
            Preferences.Key<Float> nameKey = PreferencesKeys.floatKey(key);
            Flowable<Float> exampleCounterFlow = dataStore.data().map(prefs -> prefs.get(nameKey));
            return exampleCounterFlow.blockingFirst();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}
